package com.palm.core.anno.impl;

import com.palm.core.anno.HttpCache;
import org.noear.solon.core.Aop;
import org.noear.solon.core.aspect.Interceptor;
import org.noear.solon.core.aspect.Invocation;
import org.noear.solon.core.handle.Context;
import org.noear.solon.core.handle.MethodType;
import org.noear.solon.core.handle.Result;
import org.noear.solon.data.cache.CacheService;

public class HttpCaches implements Interceptor {
    private static CacheService cs;

    static {
        Aop.context().beanOnloaded(() -> {
            Aop.getAsyn(CacheService.class, bw -> {
                cs = bw.get();
            });
        });
    }

    static class CacheItem {
        Result data;
        long timestamp;

        public CacheItem() {
        }

        public CacheItem(Result data, long timestamp) {
            this.data = data;
            this.timestamp = timestamp;
        }
    }

    @Override
    public Object doIntercept(Invocation inv) throws Throwable {
        Context ctx = Context.current();
        if (ctx == null || !MethodType.GET.name.equals(ctx.method())) {
            return inv.invoke();
        }
        if (!Result.class.isAssignableFrom(inv.method().getReturnType())) {
            return inv.invoke();
        }
        HttpCache cacheAnno = inv.method().getAnnotation(HttpCache.class);
        int maxAge = cacheAnno.maxAge();
        if (maxAge > 0) {
            ctx.headerSet("Cache-Control", "max-age=" + maxAge);
        }
        String key = "http:" + ctx.path() + ":" + ctx.queryString();

        CacheItem retItem = (CacheItem) cs.get(key);
        if (retItem != null) {
            String header = ctx.header("If-Modified-Since");
            if ((retItem.timestamp + "").equals(header)) {
                ctx.statusSet(304);
                return null;
            } else {
                ctx.headerSet("Last-Modified", retItem.timestamp + "");
                return retItem.data;
            }
        }
        Result ret = (Result) inv.invoke();
        if (ret.getCode() != Result.SUCCEED_CODE) {
            return ret;
        }
        CacheItem ci = new CacheItem(ret, System.currentTimeMillis());
        cs.store(key, ci, cacheAnno.expire());
        ctx.headerSet("Last-Modified", ci.timestamp + "");
        System.out.println("HttpCache put:"+key);
        return ret;
    }
}
